#ifndef _LCD_HD44780_H
#define _LCD_HD44780_H

/**
 * Kleine Bibliothek fuer den LCD Kontroller HD44780
 * Arbeitet ausschliesslich im 4-Bit Modus
 *
 * (c) Copyright 2007 von Enrico Homann 
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <stdlib.h>

/* #define DEBUG */

/* MCU Frequenz Voreinstellung */
#ifndef F_CPU
#define F_CPU 20.0E6					
#endif

#include <util/delay.h>

//#include "utils_avr.h"

/* Boolean definieren */
#ifndef BOOL
#define BOOL
typedef enum { false, true } bool;
#endif

#ifndef PINLAYOUT_H
/* Delayzeit der WriteChar Funktion (in µs) */
#define LCD_HD44780_WRITECHAR_DELAY			F_CPU / 4.0E5		

/* Verwendet werden nur die oberen 4 Bits */
#define LCD_HD44780_DDR DDRD
#define LCD_HD44780_PORT PORTD
#define LCD_HD44780_PIN PIND		
#define LCD_HD44780_D4 PD4				
#define LCD_HD44780_D5 PD5
#define LCD_HD44780_D6 PD6
#define LCD_HD44780_D7 PD7
#define LCD_HD44780_RS PD3
#define LCD_HD44780_RW PD2

/* Enable Leitungen fuer zwei Kontroller */
#define LCD_HD44780_DDR_E  DDRB
#define LCD_HD44780_PORT_E PORTB
#define LCD_HD44780_PIN_E  PINB		

#define LCD_HD44780_E1 PB0
#define LCD_HD44780_E2 PB1


/* Busy Flag */
#define LCD_HD44780_BF LCD_HD44780_D7

#endif

/* Befehle */

/* Loescht das Display */
#define LCD_HD44780_COMMAND_CLEARDISPLAY 			0x01 

/* Setzt den Cursor auf Position 0 */
#define LCD_HD44780_COMMAND_CURSORHOME				0x02

/* Die Anzeige des Displays wird nach einem Zeichen um eine Stelle nach
   rechts verschoben */
#define LCD_HD44780_COMMAND_ENTRYMODESET_DISPLAY_SHIFTRIGHT	0x07
/* Die Anzeige des Displays wird nach einem Zeichen um eine Stelle nach
   links verschoben */
#define LCD_HD44780_COMMAND_ENTRYMODESET_DISPLAY_SHIFTLEFT	0x05

/* Der Cursor des Displays wird nach einem Zeichen um eine Stelle nach
   rechts verschoben.*/
#define LCD_HD44780_COMMAND_ENTRYMODESET_CURSOR_SHIFTRIGHT	0x06	
/* Der Cursor des Displays wird nach einem Zeichen um eine Stelle nach
   links verschoben.*/
#define LCD_HD44780_COMMAND_ENTRYMODESET_CURSOR_SHIFTLEFT	0x04

/* Display ein, blinkenden Cursor darstellen */
#define LCD_HD44780_COMMAND_DISPLAYON_SHOWCURSOR_BLINK		0x0F
/* Display ein, nicht blinkenden Cursor darstellen */
#define LCD_HD44780_COMMAND_DISPLAYON_SHOWCURSOR_NOTBLINK	0x0E
/* Display ein, kein Cursor darstellen */
#define LCD_HD44780_COMMAND_DISPLAYON_HIDECURSOR		0x0C

/* Display aus */
#define LCD_HD44780_COMMAND_DISPLAYOFF				0x00

/* Cursor nach Zeichen schreiben nach links */
#define LCD_HD44780_COMMAND_SHIFT_CURSOR_LEFT			0x10
/* Cursor nach Zeichen schreiben nach rechts */
#define LCD_HD44780_COMMAND_SHIFT_CURSOR_RIGHT			0x14

/* Anzeige nach Zeichen schreiben nach links */
#define LCD_HD44780_COMMAND_SHIFT_DISPLAY_LEFT			0x18
/* Anzeige nach Zeichen schreiben nach rechts */
#define LCD_HD44780_COMMAND_SHIFT_DISPLAY_RIGHT			0x1C 

/* Funktionssetup: 8 Bit Modus, 2 Zeilen 5x10 Zeichen */
#define LCD_HD44780_COMMAND_FUNCTIONSET_8BIT_2LINES_5X10DOTS	0x3C
/* Funktionssetup: 8 Bit Modus, 2 Zeilen 5x8 Zeichen */
#define LCD_HD44780_COMMAND_FUNCTIONSET_8BIT_2LINES_5X8DOTS	0x38

/* Funktionssetup: 8 Bit Modus, 1 Zeile 5x10 Zeichen */
#define LCD_HD44780_COMMAND_FUNCTIONSET_8BIT_1LINE_5X10DOTS	0x34
/* Funktionssetup: 8 Bit Modus, 1 Zeile 5x8 Zeichen */
#define LCD_HD44780_COMMAND_FUNCTIONSET_8BIT_1LINE_5X8DOTS	0x30

/* Funktionssetup: 4 Bit Modus, 2 Zeilen 5x10 Zeichen */
#define LCD_HD44780_COMMAND_FUNCTIONSET_4BIT_2LINES_5X10DOTS	0x2C
/* Funktionssetup: 4 Bit Modus, 2 Zeilen 5x8 Zeichen */
#define LCD_HD44780_COMMAND_FUNCTIONSET_4BIT_2LINES_5X8DOTS	0x28   

/* Funktionssetup: 4 Bit Modus, 1 Zeile 5x10 Zeichen */
#define LCD_HD44780_COMMAND_FUNCTIONSET_4BIT_1LINE_5X10DOTS	0x24
/* Funktionssetup: 4 Bit Modus, 1 Zeile 5x8 Zeichen */
#define LCD_HD44780_COMMAND_FUNCTIONSET_4BIT_1LINE_5X8DOTS	0x20


#ifdef __cplusplus 
extern 'C' {							/* Deklaration zum Einbinden von C Code in C++ */
#endif

/**
 * void lcd_hd44780_enable ( uint8_t E )
 **
 * Erzeugt eine Flanke fuer die Enable Leitung E
 **
 * @param E Pin zum gewaehlten Enable Pin
 */

void lcd_hd44780_enableline_writeport ( uint8_t E, uint8_t port_data );

/**
 * uint8_t lcd_hd44780_readbusy ( uint8_t E )
 **
 * Liest das Busy Flag samt AC (Adress Counter) aus.
 * Arbeitet im 4 Bit Modus.
 **
 * @param E uint8_t Enable Leitung
 * @return uint8_t BusyFlag+Adress Counter (DB7-DB0)
	
 */

extern uint8_t lcd_hd44780_readbusy ( uint8_t E );

/**
 * uint8_t lcd_hd44780_isbusy ( uint8_t E )
 **
 * Liest das Busy Flag aus und liefert ein Booleanwert
 * zurueck.
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @return uint8_t BusyFlag true/false
	
 */

extern uint8_t lcd_hd44780_isbusy ( uint8_t E );

/**
 * uint8_t lcd_hd44780_getaddr ( uint8_t E )
 **
 * Liefert den Adress Counter zurueck.
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @return uint8_t AC
	
 */

extern uint8_t lcd_hd44780_getaddr ( uint8_t E );

/**
 * void lcd_hd44780_command ( uint8_t E, uint8_t ir)
 **
 * Sendet ir als Befehl/Instruktion (RS = 0) an den Kontroller E.
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @param ir uint8_t Instruktion
 */

extern void lcd_hd44780_command ( uint8_t E, uint8_t ir );

/**
 * void lcd_hd44780_writedata ( uint8_t E, uint8_t data )
 **
 * Sendet data als Daten (RS = 1) an den Kontroller E ins DDRAM/CGRAM
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @param data uint8_t Daten
 */

extern void lcd_hd44780_writedata ( uint8_t E, uint8_t data );

/**
 * void lcd_hd44780_writechar ( uint8_t E, unsigned char data )
 **
 * Sendet data als Daten (RS = 1) an den Kontroller E ins DDRAM/CGRAM
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @param data unsigned char Daten
 */

extern void lcd_hd44780_writechar ( uint8_t E, unsigned char data );

/**
 * void lcd_hd44780_writestr ( uint8_t E, char *data )
 **
 * Sendet data (String) als Daten (RS = 1) an den Kontroller E ins 
 * DDRAM/CGRAM
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @param str char* Daten
 */

extern void lcd_hd44780_writestr ( uint8_t E, char *str );

/**
 * void lcd_hd44780_setddram ( uint8_t E, uint8_t addr )
 **
 * Setzt DDRAM Adresse des Kontrollers E 
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @param addr uint8_t Adresse
 */

extern void lcd_hd44780_setddram ( uint8_t E, uint8_t addr );

/**
 * void lcd_hd44780_setcgram ( uint8_t E, uint8_t addr )
 **
 * Setzt CGRAM Adresse des Kontrollers E 
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @param addr uint8_t Adresse
 */

extern void lcd_hd44780_setcgram ( uint8_t E, uint8_t addr );

/**
 * void lcd_hd44780_gotoxy ( uint8_t E, uint8_t x, uint8_t y )
 **
 * Setzt DDRAM Adresse des Kontrollers E entsprechend x, y 
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @param x uint8_t x Koordinate (Spalte)
 * @param y uint8_t y Koordinate (Zeile)
 */

extern void lcd_hd44780_gotoxy ( uint8_t E, uint8_t x, uint8_t y );

/**
 * uint8_t lcd_hd44780_readdata ( uint8_t E )
 **
 * Liest Daten von CGRAM/DDRAM Adresse aus.
 * setddram/setcgram muss vorher ausgefuehrt worden sein.
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @return uint8_t daten
 */

extern uint8_t lcd_hd44780_readdata ( uint8_t E );

/**
 * uint8_t lcd_hd44780_readddram ( uint8_t E, uint8_t startaddr, uint8_t *buf, uint8_t length )
 **
 * Liest Daten vom DDRAM ab startaddr aus bis length in den *buf Puffer
 * Arbeitet im 4 Bit Modus
 **
 * @param E uint8_t Enable Leitung
 * @param startaddr uint8_t Startadresse ab der gelesen werden soll
 * @param buf *uint8_t Allokierter Puffer
 * @param length uint8_t Anzahl an zu lesenden Bytes
 */

extern void lcd_hd44780_readddram ( uint8_t E, uint8_t startaddr, uint8_t *buf, uint8_t length );

/**
 * void lcd_hd44780_init( uint8_t E )
 **
 * Initialisiert das Display nach Datenblatt in den 4-Bit Modus
 * Kontroller E
 *
 **
 * @param E uint8_t Enable Bit Kontroller E
 * @param fs uint8_t Function Set (Setup 4bit, Anzahl Zeilen, etc) 
 * @param es uint8_t Entrymode Set (Shift Left/Right) 
 */

extern void lcd_hd44780_init ( uint8_t E, uint8_t fs, uint8_t es, uint8_t ds );

#ifdef __cplusplus					
}							/* Abschluss der Deklaration zum Einbinden von C Code in C++ */
#endif


#endif /* _LCD_HD44780_H */
